
/**
 * @author wang
 * @editer weilan
 * @editTime 2020.06.16
 * @name 用于ws的mixin
 * @description WS用于Vue.mixin,混入Vue后会自动创建一个websocket实例this.ws,
    该实例会在Vue组件触发deactived和beforeDestroy事件时自动关闭,
    当wsOptions发生变化时会重新创建ws实例
    @param {Object} wsOptions {url: websocket地址, maxReconnectCount: 最大重连次数}
    @example 
     import { WS } from "@/library/js/ws"
        export default {
            mixins: [WS],
            method:{
                test(){
                    this.ws.onmessage = ( message ) =>{
                        console.log(message)
                    }
                    let msg ={
                        name: 'xxx',
                        age: 18
                    }

                    this.ws.send( JSON.stringify(msg) )
                }
            }
        }
 */
// import md5 from "crypto-js/md5";
import { Time } from "wl-core"
import { config } from '../../../../../config/env-configs'

const WS = {
    data() {
        return {
            wsOptions: {
                url: config.device.ws.url,
                maxReconnectCount: config.device.ws.maxReconnectCount,
            }, // 配置项
            readyState: null, // ws状态
            ws: null, // ws实例
            types: {
                bind: 'bind', // 订阅
                unbind: 'unbind', // 取消订阅
                read: 'read', // 读
                write: 'write', // 写
            },
            wsSendData: [], // 要发送数据
            timer: null
        }
    },
    methods: {
        // 创建连接
        createWs() {
            if (this.readyState === WebSocket.OPEN || this.readyState === WebSocket.CONNECTING) return;
            const base64_time = window.btoa(Time.quickFormat(new Date(), 'YYYY-MM-DD HH:mm:ss'));
            const wsIndex = Math.random();
            let url = (/^ws/.test(this.wsOptions.url) ? this.wsOptions.url : 'ws://' + window.location.host + this.wsOptions.url) + '?token=' + base64_time + "&index=" + wsIndex;

            this.ws = new WebSocket(url);
            this.ws.onclose = this.wsOnClose;
            this.ws.onerror = this.wsOnError;
            this.ws.onmessage = this.wsOnMessage;
            this.ws.onopen = this.wsOnOpen;
            this.readyState = this.ws.readyState;
            this.keepAlive();
        },
        // 重新连接
        reconnect() {
            let reconnectCount = 0;
            let connect = () => {
                reconnectCount += 1;
                setTimeout(() => {
                    this.createWs();
                }, reconnectCount * 1500)
                if (reconnectCount >= this.wsOptions.maxReconnectCount) {
                    reconnectCount = null;
                    return;
                }
                connect();
            }
            connect();
        },
        // 关闭连接
        wsClose() {
            this?.ws?.close?.();
        },
        wsOnMessage({ data }) {
            console.log(data)
        },
        // 连接错误
        wsOnError(event) {
            console.log('webSocket Error: \n', event)
        },
        // 连接关闭
        wsOnClose(e) {
            this.readyState = this.ws.readyState;
            clearInterval(this.timer);
            this.timer = null;
            console.log('websocket 断开: ' + e.code + ', ' + e.reason + ', ' + e.wasClean + ', ' + Time.quickFormat(new Date(), 'YYYY-MM-DD HH:mm:ss'))
        },
        // 连接开启
        wsOnOpen() {
            console.log('webSocket opened ' + Time.quickFormat(new Date(), 'YYYY-MM-DD HH:mm:ss'))
            this.readyState = this.ws.readyState;
        },
        // 发送数据
        wsOnSend(data) {
            // 增加md5时间戳加密
            // const md5_time = md5(new Date().getTime()).toString()
            const ws_data = JSON.stringify(data);
            this.ws?.send(ws_data);
        },
        // 保持心跳
        keepAlive() {
            this.timer = setInterval(() => {
                this.wsOnSend({ 'keep-alive': true })
            }, 60000)
        }
    },
    watch: {
        wsOptions: {
            immediate: true,
            handler() {
                if (this.ws) {
                    this.ws.close();
                    this.ws.onclose = () => this.reconnect();
                } else {
                    this.reconnect();
                }
            }
        },
        // 观察要发送数据发生变化执行ws.send
        wsSendData(val) {
            if (this.readyState !== 1 || val.length === 0) return;
            const data_length = val.length - 1;
            val.forEach((i, idx) => {
                this.wsOnSend(i);
                if (idx === data_length) {
                    this.wsSendData = []
                }
            })
        },
        // 监听ws状态为1时ws为开启状态，触发发送
        readyState(val) {
            if (val === 1 && this.wsSendData.length > 0) {
                this.wsSendData.sort();
            }
        }
    },
    deactived() {
        this.wsClose();
    },
    beforeDestroy() {
        this.wsClose();
    }
}

export default WS